package com.dpkit.core;

import com.dpkit.adapter.OrmAdapter;
import com.dpkit.adapter.orm.definition.EntityDefinition;
import com.dpkit.manager.factory.DynamicEntityFactory;
import com.dpkit.processor.DPKitTemplateProcessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * DPKit核心服务实现
 */
public class DPKitDPKitCoreEngineImpl implements DPKitCoreEngine {
    private static final Logger logger = LoggerFactory.getLogger(DPKitDPKitCoreEngineImpl.class);
    
    private final DPKitTemplateProcessor templateProcessor;
    private final DynamicEntityFactory entityFactory;
    private final OrmAdapter ormAdapter;
    private final ObjectMapper objectMapper;
    
    public DPKitDPKitCoreEngineImpl(DPKitTemplateProcessor templateProcessor,
                          DynamicEntityFactory entityFactory,
                          OrmAdapter ormAdapter) {
        this.templateProcessor = templateProcessor;
        this.entityFactory = entityFactory;
        this.ormAdapter = ormAdapter;
        this.objectMapper = new ObjectMapper();
    }
    
    @Override
    @Transactional
    public int processAndPersist(String templateName, String jsonData) throws IOException {
        EntityDefinition definition = templateProcessor.loadTemplate(templateName);
        Class<?> entityClass = entityFactory.createEntityClass(definition);
        List<Object> entities = templateProcessor.process(templateName, jsonData);
        
        if (entities.isEmpty()) {
            return 0;
        }
        
        switch (definition.getSaveStrategy()) {
            case SAVE:
                ormAdapter.batchSave(entityClass.getSimpleName(), entities);
                break;
            case UPDATE:
                ormAdapter.batchUpdate(entityClass.getSimpleName(), entities);
                break;
            case SAVE_OR_UPDATE:
            default:
                ormAdapter.batchSaveOrUpdate(entityClass.getSimpleName(), entities);
        }
        
        return entities.size();
    }
    
    @Override
    @Transactional
    public int batchProcessAndPersist(String templateName, List<String> jsonDataList) throws IOException {
        AtomicInteger counter = new AtomicInteger(0);
        
        jsonDataList.forEach(json -> {
            try {
                counter.addAndGet(processAndPersist(templateName, json));
            } catch (IOException e) {
                logger.error("Failed to process JSON data: {}", json, e);
                throw new RuntimeException(e);
            }
        });
        
        return counter.get();
    }
    
    @Override
    public Class<?> getEntityClass(String templateName) throws IOException {
        EntityDefinition definition = templateProcessor.loadTemplate(templateName);
        return entityFactory.createEntityClass(definition);
    }
    
    @Override
    public Object createEntityInstance(String templateName, String jsonData) throws IOException {
        EntityDefinition definition = templateProcessor.loadTemplate(templateName);
        Class<?> entityClass = entityFactory.createEntityClass(definition);
        List<Object> entities = templateProcessor.process(templateName, jsonData);
        
        if (entities.isEmpty()) {
            throw new IllegalArgumentException("No valid data found in JSON");
        }
        
        return entities.get(0);
    }
    
    @Override
    public List<Map<String, Object>> nativeQuery(String sql, Map<String, Object> params) {
        return ormAdapter.nativeQuery(sql, params);
    }
    
    @Override
    public void refreshCache() {
        entityFactory.clearCache();
    }
    
    // 内部辅助方法
    private Map<String, Object> convertEntityToMap(Object entity) {
        try {
            String json = objectMapper.writeValueAsString(entity);
            return objectMapper.readValue(json, Map.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert entity to map", e);
        }
    }
}